import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;


public class CurveFitOther extends FitnessFunction {
	int size;
	double [] testX;
	double [] testY;
	
	public CurveFitOther() throws NumberFormatException, IOException{
		
		name = "Curve Fitting Problem Other";
//		Create Table of X values from input file
		Scanner input = new Scanner(new FileReader (Parameters.dataInputFileName));
		size = input.nextInt();
		testX = new double[size];
		testY = new double[size];
		for (int i=0; i<size; i++){
			testX[i] = input.nextDouble();
			testY[i] = input.nextDouble();
		}
		
		if(Parameters.geneSize != 5){
			System.err.println("Must have at least gene size equal to 5 to run correctly");
		}
		
		input.close();
	}
	
	@Override
	public void doRawFitness(Chromo X){
		double difference = 0;
		double esty = 0;
		double A = 0,B = 0,C = 0,D = 0,E = 0;
		int Abit = 0,Bbit = 0,Cbit = 0,Dbit = 0,Ebit = 0;
		X.rawFitness = 0;
		int i = 0,j = 0;
		
		
		while(i<(Parameters.numGenes * Parameters.geneSize - 4)){
			
			if(X.chromo.charAt(i) == '1'){
				if( i == 0){
					Abit = 1;
				}else{
					A = A + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}
			
			if(X.chromo.charAt(i + 1) == '1'){
				if( i == 0){
					Bbit = 1;
				}else{
					B = B + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}

			if(X.chromo.charAt(i + 2) == '1'){
				if( i == 0){
					Cbit = 1;
				}else{
					C = C + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}

			if(X.chromo.charAt(i + 3) == '1'){
				if( i == 0){
					Dbit = 1;
				}else{
					D = D + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}

			if(X.chromo.charAt(i + 4) == '1'){
				if( i == 0){
					Ebit = 1;
				}else{
					E = E + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}
		    j++;
			i = i + 5;
		}
		
		if(Abit == 1){
			A = A*-1;
		}
		if (Bbit == 1){
			B = B*-1;
		}
		if (Cbit == 1){
			C = C*-1;
		}
		if (Dbit == 1){
			D = D*-1;
		}
		if (Ebit == 1){
			E = E*-1;
		}
		
		for (int z=0; z<size; z++){
			esty = (A*Math.pow(testX[z],2)) + (B*testX[z]) + C + (D*Math.sin(testX[z])) + (E*Math.cos(testX[z]));
			difference = Math.abs(esty-testY[z]);
			X.rawFitness = X.rawFitness + difference;
		}
		
		X.rawFitness = X.rawFitness/size;
	}
	
	@Override
	public void doPrintGenes(Chromo X, FileWriter output) throws java.io.IOException{
		//output.write("   RawFitness");
		//output.write("\n        ");
		/*
		for (int i=0; i<Parameters.numGenes; i++){
			Hwrite.right(X.getPosIntGeneValue(i),11,output);
		}*/
		double A = 0,B = 0,C = 0,D = 0,E = 0;
		int Abit = 0,Bbit = 0,Cbit = 0,Dbit = 0,Ebit = 0;
		int i = 0,j = 0;
		float values[] = new float[5];
		
		Hwrite.right((int) X.rawFitness,13,output);
		
		while(i<(Parameters.numGenes * Parameters.geneSize - 4)){
			
			if(X.chromo.charAt(i) == '1'){
				if( i == 0){
					Abit = 1;
				}else{
					A = A + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}
			
			if(X.chromo.charAt(i + 1) == '1'){
				if( i == 0){
					Bbit = 1;
				}else{
					B = B + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}

			if(X.chromo.charAt(i + 2) == '1'){
				if( i == 0){
					Cbit = 1;
				}else{
					C = C + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}

			if(X.chromo.charAt(i + 3) == '1'){
				if( i == 0){
					Dbit = 1;
				}else{
					D = D + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}

			if(X.chromo.charAt(i + 4) == '1'){
				if( i == 0){
					Ebit = 1;
				}else{
					E = E + Math.pow(2, ((Parameters.numGenes -1) - j));
				}
			}
		    j++;
			i = i + 5;
		}
		
		if(Abit == 1){
			A = A*-1;
		}
		if (Bbit == 1){
			B = B*-1;
		}
		if (Cbit == 1){
			C = C*-1;
		}
		if (Dbit == 1){
			D = D*-1;
		}
		if (Ebit == 1){
			E = E*-1;
		}
		
		values[0] = (float) A;
		values[1] = (float) B;
		values[2] = (float) C;
		values[3] = (float) D;
		values[4] = (float) E;
		
		output.write("\n\n");
		
		output.write("\nGene Float: ");
		for(j=0;j<5;j++){
			Hwrite.rightFloat(values[j],output);
		}
		
		
		output.write("\n\n");
		
		output.write("\nGene: ");
		for (i=0; i<Parameters.numGenes; i++){
			Hwrite.right(X.getGeneAlpha(i),Parameters.geneSize+1,output);
		}
		
		output.write("\n\n");
		return;
	}
}
